package com.mzkj.wanjulaile.mobile.api.modules.weChat.controller;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.mzkj.common.data.StatusCode;
import com.mzkj.common.utils.Collections3;
import com.mzkj.common.utils.OrderUilts;
import com.mzkj.common.utils.StringUtils;
import com.mzkj.wanjulaile.mobile.api.common.controller.BaseController;
import com.mzkj.wanjulaile.mobile.api.common.entity.ResultEntity;
import com.mzkj.wanjulaile.mobile.api.common.utils.RedisUtil;
import com.mzkj.wanjulaile.mobile.api.modules.account.entity.Account;
import com.mzkj.wanjulaile.mobile.api.modules.account.entity.BuyVip;
import com.mzkj.wanjulaile.mobile.api.modules.account.entity.VipScheme;
import com.mzkj.wanjulaile.mobile.api.modules.account.service.AccountService;
import com.mzkj.wanjulaile.mobile.api.modules.account.service.BuyVipService;
import com.mzkj.wanjulaile.mobile.api.modules.account.service.VipSchemeService;
import com.mzkj.wanjulaile.mobile.api.modules.coupon.entity.AccountCoupon;
import com.mzkj.wanjulaile.mobile.api.modules.coupon.entity.Coupon;
import com.mzkj.wanjulaile.mobile.api.modules.coupon.service.AccountCouponService;
import com.mzkj.wanjulaile.mobile.api.modules.order.constant.Constant;
import com.mzkj.wanjulaile.mobile.api.modules.order.entity.Order;
import com.mzkj.wanjulaile.mobile.api.modules.order.service.DelayService;
import com.mzkj.wanjulaile.mobile.api.modules.order.service.OrderService;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.entity.AuthToken;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.entity.NotifyData;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.entity.NotifyReturnData;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.entity.WxConstant;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.service.NotifyReturnService;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.service.WechatPayService;
import com.mzkj.wanjulaile.mobile.api.modules.weChat.utils.WechatUtils;
import com.thoughtworks.xstream.XStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

/**
 * Copyright © 2016 上海美挚网络. All rights reserved.
 *
 * @Projec: meilein
 * @Package:in.meile.print.modules.mobile.web
 * @Description:微信支付控制类 支付订单生产;支付通知处理等
 * @author:bing
 * @date:16/5/6 上午10:06
 * @version:V1.0
 */
@Controller("weChatPayController")
public class WechatPayController extends BaseController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private WechatPayService wechatPayService;
    @Autowired
    private NotifyReturnService notifyReturnService;
    @Autowired
    private VipSchemeService vipSchemeService;
    @Autowired
    private BuyVipService buyVipService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private AccountCouponService accountCouponService;
    @Autowired
    private DelayService delayService;

    private static final String ORDER = "order";
    private static final String VIP = "vip";

    /**
     * 微信支付请求
     *
     * @param type：order-订单支付，vip-会员费支付 id：会员制度ID/订单ID accountCouponId：优惠劵
     * @return string
     */
    @RequestMapping(value = "auth/wechat/wechatPay")
    @ResponseBody
    public ResultEntity<Map> wechatPay(HttpServletRequest request, String type, String id,String accountCouponId) {
        ResultEntity<Map> resultEntity = new ResultEntity<Map>();
        String resultCode;
        String returnCode;
        SortedMap<String, Object> resultMap = null;
        BuyVip buyVip = null;
        Order order = null;
        Map<String, Object> verifyResult = null;
        Map<String, Object> map = Maps.newHashMap();
        map.put("remoteIp", request.getRemoteAddr());
        String accountId= (String)request.getAttribute("accountId");
        if (VIP.equalsIgnoreCase(type)) {
            VipScheme vipScheme = vipSchemeService.get(id);
            if (vipScheme != null) {
                buyVip = new BuyVip();
                Account account=accountService.getAccount(accountId);
                // 验证account购买资格
                verifyResult = buyVipService.verifyAccount(account, vipScheme,accountCouponId);
                if ((Boolean) verifyResult.get("isDownVip")) {
                    resultEntity.setStatusCode(StatusCode.SC4008.getValue());
                    resultEntity.setMsg("您目前是" + account.getVipTypeText() + "，无法直接购买" + vipScheme.getVipCategory().getName() + "套餐，可先取消当前会员再进行购买");
                    return resultEntity;
                }
                buyVip.setAccount(account);
                //是否首次购买
                List<BuyVip> buyVipList = buyVipService.findListByAccountId(account.getId());
                if (!Collections3.isEmpty(buyVipList)){
                    buyVip.setFirstFlag("1");
                }
                buyVip.setVipScheme(vipScheme);
                buyVip.setFee(vipScheme.getFee());
                accountService.calTotalDeposit(account);
                if (account.getTotalDeposit() == null || account.getTotalDeposit() == 0) {
                    buyVip.setDeposit(vipScheme.getDeposit());
                } else {
                    buyVip.setDeposit(0);
                }
                //设置优惠券减免金额
                if (!StringUtils.isEmpty(accountCouponId)) {
                    setBuyVipDiscountFee(accountCouponId, buyVip, vipScheme);
                }
                buyVip.setPayNumber(OrderUilts.generateOrderNumber());
                resultMap = wechatPayService.unifiedVip(buyVip, map);
            }
        } else if (ORDER.equalsIgnoreCase(type)) {
            order = orderService.get(id);
            //校验是否后台取消了
            ResultEntity<Map> validateResult = orderService.validateOrderStatus(order, resultEntity);
            if (!validateResult.getStatusCode().equals(StatusCode.SC0.getValue())){
                return resultEntity;
            }
            if((order.getShipFee()-(order.getCouponVal() == null ? 0 : order.getCouponVal()))==0){
                try{
                    order.setPayStatus(Constant.PAYSTATUS_PAID);
                    Account account = accountService.get2(accountId);
                    BuyVip curBuyVip = buyVipService.get(account.getCurBuyVip().getId());
                    // 当前购买的会员套餐设置生效时间
                    buyVipService.updateOrderVipInfo(order,account,curBuyVip);
                    resultEntity.setStatusCode(StatusCode.SC10.getValue());
                    resultEntity.setMsg(StatusCode.SC10.getDesc());
                }catch (Exception e){
                    e.printStackTrace();
                    resultEntity.setStatusCode(StatusCode.SC5000.getValue());
                    resultEntity.setMsg(StatusCode.SC5000.getDesc());
                }
                return resultEntity;
            }else {
                resultMap = wechatPayService.unifiedOrder(order, map);
            }
        } else {
            resultEntity.setStatusCode(StatusCode.SC4000.getValue());
            resultEntity.setMsg("请求参数错误");
            logger.error("请求参数错误,没有该type");
            return resultEntity;
        }
        resultCode = (String) resultMap.get("result_code");
        returnCode = (String) resultMap.get("return_code");
        SortedMap<String, Object> signMap;
        if (WxConstant.RETURN_SUCCESS.equals(resultCode) && WxConstant.RETURN_SUCCESS.equals(returnCode)) {
            if (VIP.equalsIgnoreCase(type) && buyVip != null) {
                buyVip.setPayStatus(BuyVip.PAYSTATUS_NOT_PAID);
                //第一次生成记录 押金剩余金额 = 押金金额
                buyVip.setRealDeposit(buyVip.getDeposit());
                buyVipService.insert(buyVip);
                logger.info("WechatPay日志：生成buyVip记录成功");
            }
            signMap = wechatPayService.createPayParam(resultMap);
            resultEntity.setStatusCode(StatusCode.SC0.getValue());
            resultEntity.setMsg(StatusCode.SC0.getDesc());
            resultEntity.setData(signMap);
            logger.info("WechatPay日志：统一下单成功");
        } else {
            logger.error("WechatPay日志：统一下单失败,原因:" + resultMap.get("err_code_des"));
            resultEntity.setStatusCode((String)resultMap.get("err_code"));
            resultEntity.setMsg((String) resultMap.get("err_code_des"));
        }
        return resultEntity;
    }

    private void setBuyVipDiscountFee(String accountCouponId, BuyVip buyVip, VipScheme vipScheme) {
        //优惠券类型 折扣
        AccountCoupon accountCoupon = new AccountCoupon();
        accountCoupon.setId(accountCouponId);
        buyVip.setAccountCoupon(accountCoupon);
        AccountCoupon accountCoupon1 = accountCouponService.getById(accountCoupon);
        Coupon coupon = accountCoupon1.getCoupon();
        //校验优惠券是否符合购买vip类型
        if (coupon != null && coupon.getVipSchemeType().indexOf(vipScheme.getId()) >= 0) {
            if (coupon.getCouponType().equals("1")) {
                //会员购买抵用券
                if (coupon.getCouponMode() == 1) {
                    //满减券
                    if (buyVip.getFee() > (coupon.getMinAmount() == null ? 0 : coupon.getMinAmount())) {
                        buyVip.setCouponVal(Integer.valueOf(coupon.getFaceValue()));
                    }
                } else if (coupon.getCouponMode() == 2) {
                    //折扣券
                    int discountFee = buyVip.getFee() - buyVip.getFee() * coupon.getDiscount() / 100;
                    if (coupon.getMaxDiscountMoney() != null && discountFee > coupon.getMaxDiscountMoney()) {
                        buyVip.setCouponVal(Integer.valueOf(coupon.getMaxDiscountMoney()));
                    } else {
                        buyVip.setCouponVal(discountFee);
                    }
                }
            }
        }
    }

    /**
     * 微信支付成功 后台通知
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/m/wechat/notify_url")
    public void wxPayNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("-----------处理订单微信支付结果回调通知------------");
        //通过后台通知判断支付是否成功
        SortedMap<String, Object> map = Maps.newTreeMap();
        NotifyReturnData returnData = new NotifyReturnData();
        try {
            map = WechatUtils.parseXml(request.getInputStream());
            ObjectMapper om = new ObjectMapper();
            JSONObject jsonObject = new JSONObject(map);
            returnData = om.readValue(jsonObject.toString(), NotifyReturnData.class);
        } catch (Exception e) {
            logger.error("解析微信支付通知异常", e);
        }
        //首先需要验证此通知是否是微信服务器发出的通知
        if (WechatUtils.checkResponseSign(map)) {
            try {
                //TODO 判断业务数据是否已处理
                Order order = orderService.getByOrderNumber(returnData.getOut_trade_no());
                if (null != order && Constant.PAY_STATUS_NOT_PAID_.equals(order.getPayStatus())) {
                    order.setPayStatus(Constant.PAYSTATUS_PAID);
                    Account account = order.getAccount();
                    account = accountService.getAccount(account.getId());
                    BuyVip curBuyVip = buyVipService.get(account.getCurBuyVip().getId());
                    // 账号vip时效
                    buyVipService.updateOrderVipInfoByWXPay(order,account,curBuyVip,returnData);
                    // 订单支付 从delay队列删除 redis中删除
                    removeFromRedisAndQueue(order.getId());
                }
                //通知微信服务器通知处理成功
                NotifyData notifyData = new NotifyData();
                notifyData.setReturnCode("SUCCESS");
                notifyData.setReturnMsg("处理支付通知成功");
                XStream xStream = WechatUtils.xStream2;
                xStream.autodetectAnnotations(true);
                xStream.alias("xml", NotifyData.class);
                String xml = xStream.toXML(notifyData);
                PrintWriter out = response.getWriter();
                out.print(xml);
                out.close();
                logger.info("-----------处理订单微信支付结果通知成功------------");
            } catch (Exception e) {
                logger.error("处理订单微信支付结果通知失败");
                logger.error(e.getMessage(), e);
            }
        }else {
            logger.error("验证通知不是由微信服务器发出");
        }
    }
    private void removeFromRedisAndQueue(String orderId) {
        // 支付 从队列中删除
        delayService.remove(orderId);
        // 从redis中删除
        RedisUtil.remove(Constant.RedisKey_DSHORDER_PREFIX + orderId);
        logger.info("支付成功,从Queue,redis中删除>>>>>>>>" + orderId);
    }

    /**
     * 微信支付成功 后台通知
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/m/wechat/vip_notify_url")
    public void wxVipPayNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("-----------处理购买会员微信支付结果回调通知------------");
        //通过后台通知判断支付是否成功
        SortedMap<String, Object> map = Maps.newTreeMap();
        NotifyReturnData returnData = new NotifyReturnData();
        try {
            map = WechatUtils.parseXml(request.getInputStream());
            ObjectMapper om = new ObjectMapper();
            JSONObject jsonObject = new JSONObject(map);
            returnData = om.readValue(jsonObject.toString(), NotifyReturnData.class);
        } catch (Exception e) {
            logger.error("解析微信支付通知异常", e);
        }
        //首先需要验证此通知是否是微信服务器发出的通知
        if (WechatUtils.checkResponseSign(map)) {
            try {
                // 判断业务数据是否已处理
                BuyVip buyVip = buyVipService.getByPayNumber(returnData.getOut_trade_no());
                if (null != buyVip && BuyVip.PAYSTATUS_NOT_PAID.equals(buyVip.getPayStatus())) {
                    buyVip.setPayStatus(BuyVip.PAYSTATUS_PAID);
                    Account account = new Account();
                    account.setId(buyVip.getAccount().getId());
                    //设置购买vip的账号相关信息
                    buyVipService.updateAccountVipInfo(account, buyVip,returnData);
                }
                //通知微信服务器通知处理成功
                NotifyData notifyData = new NotifyData();
                notifyData.setReturnCode("SUCCESS");
                notifyData.setReturnMsg("处理支付通知成功");
                XStream xStream = WechatUtils.xStream2;
                xStream.autodetectAnnotations(true);
                xStream.alias("xml", NotifyData.class);
                String xml = xStream.toXML(notifyData);
                PrintWriter out = response.getWriter();
                out.print(xml);
                out.close();
                logger.info("-----------处理购买会员订单微信支付结果通知成功------------");
            } catch (Exception e) {
                logger.error("处理购买会员微信支付结果通知失败");
                logger.error(e.getMessage(), e);
            }
        }else {
            logger.error("验证通知不是由微信服务器发出");
        }
    }

    /**
     * 微信支付请求
     *
     * @param model
     * @param
     * @param
     * @return
     */
    @RequestMapping(value = "/m/wechat/pay")
    public String orderPay(HttpServletRequest request, Model model, Long state) {
        AuthToken authToken = WechatUtils.getTokenByAuthCode(request);
        if ("40029".equals(authToken.getErrcode())) {
            return "redirect:/m/auth/wechat/orderList";
        }
        if (null == state) {
            Order order = new Order();
            model.addAttribute("order", order);
            return "/mobile/modules/mall/orderComplete";
        }
        Order order = orderService.get(state + "");
        Map<String, Object> map = Maps.newHashMap();
        map.put("openId", authToken.getOpenid());
        map.put("remoteIp", request.getRemoteAddr());
        SortedMap<String, Object> resultMap = wechatPayService.unifiedOrder(order, map);
        String resultCode = (String) resultMap.get("result_code");
        String returnCode = (String) resultMap.get("return_code");
        if (WxConstant.RETURN_SUCCESS.equals(resultCode) && WxConstant.RETURN_SUCCESS.equals(returnCode)) {
            String appId = (String) resultMap.get("appid");
            String timeStamp = WechatUtils.getTimeStamp();
            String prepayId = "prepay_id=" + resultMap.get("prepay_id");
            String nonceStr = WechatUtils.getRandomStr(20);
            SortedMap<String, Object> signMap = Maps.newTreeMap();
            signMap.put("appId", appId);
            signMap.put("package", prepayId);
            signMap.put("timeStamp", timeStamp);
            signMap.put("nonceStr", nonceStr);
            signMap.put("signType", "MD5");
            model.addAttribute("timeStamp", timeStamp);
            model.addAttribute("appId", appId);
            model.addAttribute("nonceStr", nonceStr);
            model.addAttribute("prepayId", prepayId);
            model.addAttribute("paySign", WechatUtils.getSign(signMap));
        } else {
            logger.error("统一下单失败,订单ID:" + state + ",原因:" + resultMap.get("err_code_des"));
            return "";
        }
        return "mobile/modules/wxpay/h5Pay";
    }
}
